package com.ambitor.ipro.app.sche;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.ambitor.grass.sql.dao.SuperDao;
import com.ambitor.grass.util.data.DataMap;
import com.ambitor.grass.util.data.DatasetList;
import com.ambitor.grass.util.data.IData;
import com.ambitor.grass.util.data.IDataset;
import com.ambitor.ipro.app.gen.TaskGeneratorHelper;
import com.ambitor.ipro.entities.TradeState;
import com.ambitor.ipro.entities.TradeType;
import com.ambitor.ipro.entities.UninstallSetting;
import com.ambitor.ipro.entities.UserProValidFlag;
import com.ambitor.ipro.exceptions.ProException;
import com.ambitor.ipro.labelParser.IntellLabelParser;
import com.ambitor.ipro.labelParser.IntellLabelParserFactory;
import com.ambitor.ipro.service.TopService;
import com.ambitor.ipro.util.Constants;
import com.ambitor.ipro.util.ResultCode;
import com.ambitor.ipro.util.SkyenccUtil;
import com.ambitor.ipro.util.StringUtil;
import com.ambitor.ipro.util.Utils;
import com.taobao.api.domain.Item;
import com.taobao.api.domain.UserSubscribe;

public class Installer extends BaseExecutor {

	public Installer(SuperDao superDao, TopService topService) {
		super(superDao, topService);
	}

	@SuppressWarnings("unchecked")
	public void install() {
		logTaskStart();
		try {
			IData userSession = getUserSession();
			validateUserSubscribeInfo(userSession);
			IData userPro = getUserPro();
			IData userStyle = getUserStyle(userPro);
			int[] result = _install(userSession, userPro, userStyle);
			logTaskEnd(result);
		} catch (ProException e) {// 执行出现异常，记录日志并更改状态
			logTaskQuit(e);
		}
	}

	@SuppressWarnings("unchecked")
	private int[] _install(IData userSession, IData userPro, IData userStyle)
			throws ProException {
		InstallerHelper installerHelper = new InstallerHelper(superDao,
				topService, userSession, userPro, userStyle);
		List<Item> intellItemList = new ArrayList<Item>();
		List<Item> staticItemList = getStaticItemsToBePromoted(userSession,
				userPro);
		List<String> installIids = this.getInstallIids(userPro, userSession);
		if (installIids == null || installIids.size() == 0) {
			throw new ProException(ResultCode.BUSSINESS_EXCEPTION, "获取待安装的宝贝为空");
		}
		intellItemList = this.getIntellItemsToBePromoted(userSession, userPro,
				installIids.get(0));

		boolean isIntellLabelSimple = Utils.isIntellLabelSimple(userPro
				.getString("INTELL_SETTING"));
		if (isIntellLabelSimple && staticItemList.size() == 0
				&& intellItemList.size() == 0) {
			throw new ProException(ResultCode.BUSSINESS_EXCEPTION, "获取待推广的宝贝为空");
		}

		List<Item> allItems = installerHelper.buildAllItemsToBePromoted(
				staticItemList, intellItemList);

		String installPlaces = task.getString("PLACE");
		List<String> proModules = installerHelper.buildPromHTML(allItems,
				installPlaces.split(","));

		int errorNum = 0;
		IDataset tradePros = new DatasetList();
		for (String installIid : installIids) {
			IData tradePro = new DataMap();
			tradePro.put("BATCH_ID", task.getString("BATCH_ID"));
			tradePro.put("IID", installIid);
			// tradePro.put("PLACE", userPro.getString("INSTALL_PLACE"));
			tradePro.put("LOG_TIME", SkyenccUtil.formatDate(new Date()));
			tradePro.put("EXP_TYPE", null);
			tradePro.put("EXP_DESC", null);
			tradePro.put("EXP_CODE", null);
			tradePro.put("EXP_MSG", null);
			tradePro.put("EXP_SUB_CODE", null);
			tradePro.put("EXP_SUB_MSG", null);
			try {
				if (isIntellLabelSimple == false) {
					intellItemList = this.getIntellItemsToBePromoted(
							userSession, userPro, installIid);
					if (staticItemList.size() == 0
							&& intellItemList.size() == 0) {
						throw new ProException(ResultCode.BUSSINESS_EXCEPTION,
								"获取待推广的宝贝为空");
					}

					allItems = installerHelper.buildAllItemsToBePromoted(
							staticItemList, intellItemList);
					proModules = installerHelper.buildPromHTML(allItems,
							installPlaces.split(","));
				}

				installerHelper.installInTaobao(installIid, proModules);
				tradePro.put("TRADE_STATE", Constants.FLAG_YES);// 成功
				//tradePro.put("PRO_MODULE", proModules.get(0));
			} catch (ProException e) {
				errorNum++;
				tradePro.put("TRADE_STATE", Constants.FLAG_NO);// 失败
				tradePro.put("EXP_TYPE", e.getType());
				tradePro.put("EXP_DESC", e.getDesc());
				tradePro.put("EXP_CODE", e.getCode());
				tradePro.put("EXP_MSG", e.getMsg());
				tradePro.put("EXP_SUB_CODE", e.getSubCode());
				tradePro.put("EXP_SUB_MSG", e.getSubMsg());
				continue;
			} finally {
				tradePros.add(tradePro);
			}
		}

		try {
			// updateItemPros(tradePros);
			insertTradePros(tradePros);
		} catch (Exception exp) {
			logger.error("新增tradePro日志或更新item_pro出现数据库异常", exp);
		}
		return new int[] { installIids.size(), errorNum };
	}

	@SuppressWarnings("unchecked")
	private List<String> getInstallIids(IData userPro, IData userSession)
			throws ProException {
		List<String> iidList = new ArrayList<String>();
		if (retryFlag) {
			IData param = new DataMap();
			param.put("BATCH_ID", task.getString("BATCH_ID"));
			param.put("TRADE_STATE", Constants.FLAG_NO);
			try {
				IDataset dataset = superDao.queryList("TL_P_TRADE_PRO", param);
				for (int i = 0; i < dataset.size(); i++) {
					iidList.add(dataset.get(i, "IID").toString());
				}
				return iidList;
			} catch (Exception e) {
				throw new ProException(ResultCode.DB_EXCEPTION, "获取pro_id="
						+ task.getString("BATCH_ID") + "安装失败宝贝出现异常", e);
			}
		}
		List<Item> itemList = new ArrayList<Item>();
		String installSetting = userPro.getString("INSTALL_SETTING");
		String sessionId = userSession.getString("SESSION_ID");
		String nick = userSession.getString("NICK");
		if ("custom".equals(installSetting)) {
			IData param = new DataMap();
			param.put("PRO_ID", userPro.getString("PRO_ID"));
			param.put("VALID_FLAG", Constants.FLAG_YES);
			IDataset iidDataset = null;
			try {
				iidDataset = superDao.queryList("TF_P_USER_PRO_SUB", param);
			} catch (Exception e) {
				throw new ProException(ResultCode.DB_EXCEPTION,
						"获取TF_P_USER_PRO_SUB发生数据库异常", e);
			}
			for (int i = 0; i < iidDataset.size(); i++) {
				iidList.add(iidDataset.get(i, "IID").toString());
			}
		} else if ("someCategory".equals(installSetting)) {
			IData param = new DataMap();
			param.put("PRO_ID", userPro.getString("PRO_ID"));
			param.put("VALID_FLAG", Constants.FLAG_YES);
			IDataset iidDataset = null;
			try {
				iidDataset = superDao.queryList("TF_P_USER_PRO_SUB", param);
			} catch (Exception e) {
				throw new ProException(ResultCode.DB_EXCEPTION,
						"获取TF_P_USER_PRO_SUB发生数据库异常", e);
			}
			StringBuilder sellerCidsSb = new StringBuilder();
			for (int i = 0; i < iidDataset.size(); i++) {
				sellerCidsSb.append(iidDataset.get(i, "CID").toString());
				sellerCidsSb.append(",");
			}
			String sellerCids = StringUtil.trimSuffix(sellerCidsSb.toString(),
					",");
			itemList = topService.getOnSaleItemsOfSpecificSellerCat(sessionId,
					nick, sellerCids);
			for (Item item : itemList) {
				iidList.add(item.getNumIid().toString());
			}
		} else if ("itemCategory".equals(installSetting)) {
			IData param = new DataMap();
			param.put("PRO_ID", userPro.getString("PRO_ID"));
			param.put("VALID_FLAG", Constants.FLAG_YES);
			IDataset iidDataset = null;
			try {
				iidDataset = superDao.queryList("TF_P_USER_PRO_SUB", param);
			} catch (Exception e) {
				throw new ProException(ResultCode.DB_EXCEPTION,
						"获取TF_P_USER_PRO_SUB发生数据库异常", e);
			}
			StringBuilder itemCidsSb = new StringBuilder();
			for (int i = 0; i < iidDataset.size(); i++) {
				itemCidsSb.append(iidDataset.get(i, "CID").toString());
				itemCidsSb.append(",");
			}
			String itemCids = StringUtil.trimSuffix(itemCidsSb.toString(), ",");

			itemList = topService.getOnSaleItemsOfSpecificItemCat(sessionId,
					nick, itemCids);
			for (Item item : itemList) {
				iidList.add(item.getNumIid().toString());
			}
		} else if ("onSale".equals(installSetting)) {
			itemList = topService.getOnSaleItems(sessionId, nick);
			for (Item item : itemList) {
				iidList.add(item.getNumIid().toString());
			}
		} else if ("all".equals(installSetting)) {
			itemList = topService.getAllItems(sessionId, nick);
			for (Item item : itemList) {
				iidList.add(item.getNumIid().toString());
			}
		}
		return iidList;
	}

	private List<Item> getStaticItemsToBePromoted(IData userSession,
			IData userPro) throws ProException {
		List<Item> staticItemList = new ArrayList<Item>();
		int staticNum = userPro.getInt("STATIC_NUM");
		if (staticNum <= 0)
			return staticItemList;
		String staticSetting = userPro.getString("STATIC_SETTING");
		String[] staticSettingArray = staticSetting.split(",");
		String sessionId = userSession.getString("SESSION_ID");
		String nick = userSession.getString("NICK");
		int erroNum = 0;
		for (String iid : staticSettingArray) {
			Item item = null;
			try {
				item = topService.getItem(sessionId, nick, iid);
			} catch (ProException e) {
				erroNum++;
				logger.warn(e.getMessage());
				if (erroNum == staticSettingArray.length) {
					String desc = "获取" + erroNum + "个静态推广宝贝全部出错";
					throw new ProException(ResultCode.BUSSINESS_EXCEPTION,
							desc, e.getCode(), e.getMsg(), e.getSubCode(), e
									.getSubMsg());
				}
			}
			if (item != null)
				staticItemList.add(item);
		}
		return staticItemList;
	}

	@SuppressWarnings("unchecked")
	private List<Item> getIntellItemsToBePromoted(IData userSession,
			IData userPro, String installIid) throws ProException {
		List<Item> intellItemList = new ArrayList<Item>();
		int intellNum = userPro.getInt("INTELL_NUM");
		if (intellNum <= 0) {
			return intellItemList;
		}
		int staticNum = userPro.getInt("STATIC_NUM");
		String[] intellSettingArray = userPro.getString("INTELL_SETTING")
				.trim().split(",");
		if (intellSettingArray.length == 1) { // 当前web前台只能设置1个推广规则，下面代码肯定运行
			String[] labelStr = intellSettingArray[0].split(":");
			String intellLabel = labelStr[0];
			int minSumNum = intellNum + staticNum;// 取在最大重合的item的情况下也足够的item数量
			IntellLabelParser parser = IntellLabelParserFactory.instance(
					intellLabel, superDao, topService, userSession, installIid,
					minSumNum);
			intellItemList = parser.parse();
		}
		return intellItemList;
	}

	private IData getUserStyle(IData userPro) throws ProException {
		try {
			return superDao.queryByPK("TF_P_USER_STYLE", userPro);
		} catch (Exception e) {
			throw new ProException(ResultCode.DB_EXCEPTION,
					"获取TF_P_USER_STYLE时发生异常", e);
		}
	}

	@SuppressWarnings("unchecked")
	private void validateUserSubscribeInfo(IData userSession)
			throws ProException {
		Date presentDeadline = (Date) userSession.get("PRESENT_DEADLINE");
		if (presentDeadline.after(new Date())) {
			return;
		}
		String nick = userSession.getString("NICK");
		UserSubscribe userSubs = null;
		userSubs = topService.getSubscribeInfo(nick, null);
		if (userSubs == null) {
			throw new ProException(ResultCode.BUSSINESS_EXCEPTION,
					"UserSubscribe==null");
		}
		if (!"subscribeUser".equals(userSubs.getStatus())
				|| userSubs.getEndDate() == null
				|| userSubs.getEndDate().before(new Date())) {
			invalideUserPro();
			addUninstallTask();
			throw new ProException(ResultCode.BUSSINESS_EXCEPTION,
					"用户没有订购过订购已经过期");
		}
	}

	@SuppressWarnings("unchecked")
	private void invalideUserPro() {
		String sql = "update tf_p_user_pro_batch set end_time = :END_TIME, "
				+ "valid_flag = :VALID_FLAG where user_id=:USER_ID and valid_flag = '0'";
		IData param = new DataMap();
		param.put("END_TIME", super.getTime());
		param.put("VALID_FLAG", UserProValidFlag.UNVALID_EXPIRED);
		param.put("USER_ID", task.getString("USER_ID"));
		try {
			superDao.getBaseDao().executeUpdate(sql, param);
		} catch (Exception e) {
			String batchId = task.getString("BATCH_ID");
			logger.warn(task.getString("NICK") + "更新过期配置的时候发生数据库异常,batch_id="
					+ batchId, e);
		}
	}

	@SuppressWarnings("unchecked")
	private void addUninstallTask() {
		IData tradeProBatch = new DataMap();
		tradeProBatch.put("TRADE_STATE", TradeState.UN_EXECUTE);// 未执行
		tradeProBatch.put("TRADE_TYPE", TradeType.EXPIRED_UNINSTALL);// 过期卸载
		tradeProBatch.put("USER_ID", task.getString("USER_ID"));
		tradeProBatch.put("NICK", task.getString("NICK"));
		tradeProBatch.put("CREATE_TIME", super.getTime());
		tradeProBatch.put("PLAN_EXEC_TIME", super.getTime());
		tradeProBatch.put("PRIORITY", Constants.HIGH_PRIORITY);
		tradeProBatch.put("UNINSTALL_SETTING", UninstallSetting.USER_UNINSTALL);
		tradeProBatch.put("PLACE", "ALL");
		tradeProBatch.put("REMARK", "过期卸载");
		try {
			TaskGeneratorHelper.addTask(superDao, tradeProBatch);
		} catch (Exception e) {
			String batchId = task.getString("BATCH_ID");
			logger.warn(task.getString("NICK") + "添加过期删除任务的时候发生数据库异常,batch_id="
					+ batchId, e);
		}
	}

	private IData getUserPro() throws ProException {
		IData userPro = null;
		try {
			userPro = superDao.queryByPK("TF_P_USER_PRO_BATCH", task);
		} catch (Exception e) {
			throw new ProException(ResultCode.DB_EXCEPTION,
					"获取TF_P_USER_PRO_BATCH时发生异常", e);
		}
		if (!Constants.FLAG_YES.equals(userPro.getString("VALID_FLAG"))) {
			String proId = task.getString("PRO_ID");
			throw new ProException(ResultCode.BUSSINESS_EXCEPTION, "pro_id=="
					+ proId + "处于无效状态");
		}
		return userPro;
	}
}
